<script setup lang='ts'>
import {computed, onMounted, onUnmounted, ref, watch, nextTick, reactive} from 'vue'
import { useRoute } from 'vue-router'
import { NButton, NInput, useDialog, useMessage } from 'naive-ui'
import { Message } from './components'
import { useScroll } from './hooks/useScroll'
import { useChat } from './hooks/useChat'
import { HoverButton, SvgIcon } from '@/components/common'
import { useBasicLayout } from '@/hooks/useBasicLayout'
import { useChatStore } from '@/store'
import { fetchChatAPIProcess,msgHistoryAPI } from '@/api'
const socket = ref<WebSocket | null>(null); // WebSocket 对象
let controller = new AbortController()
const route = useRoute()
const dialog = useDialog()
const ms = useMessage()
const chatStore = useChatStore()
const { isMobile } = useBasicLayout()
const { addChat, updateChat, appendChatByUUid, setSendMsg1Info, getLastChatMessageInfo, getHistoryTile} = useChat()
const { scrollRef, scrollToBottom } = useScroll()
const { uuid } = route.params as { uuid: string }
const dataSources = computed(() => chatStore.getChatByUuid(+uuid))
const prompt = ref<string>('')
const loading = ref<boolean>(false)
const msgHistoryData = reactive({

})

onMounted(() => {
  const ws = new WebSocket('ws://35.89.148.230:8091/chatGptSocket'); // 创建 WebSocket 对象，指定连接的地址
  socket.value = ws;
  // 监听连接事件
  ws.onopen = () => {
    console.log('WebSocket 连接成功');
  };
  // 监听错误事件
  ws.onerror = (event) => {
    console.error('WebSocket 连接错误:', event);
  };
  // 监听关闭事件
  ws.onclose = (event) => {
    console.warn('WebSocket 连接关闭:', event);
  };
  // 监听消息事件
  ws.onmessage = (event) => {
    const data = JSON.parse(event.data)
    //实现字符一个一个出现的主要效果
    appendChatByUUid(
        +uuid,
        dataSources.value.length - 1,
        {
          dateTime: new Date().toLocaleString(),
          text: data.text,
          loading: false,
          inversion: false,
          error: false,
          conversationOptions: null,
          requestOptions: { prompt: data.text, options: null },
        }
    )
    if (data.status === true){  //为true表示对话结束
      isMobile.value = false    //开启用户输入
      loading.value = false    //发送按钮开启
    }
  };
});

//点击发送请求
function handleSubmit() {
  if (socket.value && socket.value.readyState === WebSocket.OPEN) {
    const message = prompt.value;
    const lastMsgList = new Array();
    let title = getHistoryTile(+uuid)?.title;
    if(title != 'New Chat' && title != null) {
      lastMsgList.push(setSendMsg1Info({role:"system", content: title}))
    }
    const length = dataSources.value.length
    if(length >= 2){
      for(let i = length; i >= 1; i--){
        if(lastMsgList.length < 4){
          let lastMyMsg = getLastChatMessageInfo(+uuid, i)
          if(lastMyMsg != null){
            lastMsgList.push(setSendMsg1Info({role: "user", content: lastMyMsg.text}))
          }
        }
      }
    }
    lastMsgList.push(setSendMsg1Info({role: "user", content: message}))
    socket.value.send(JSON.stringify(lastMsgList));
    //添加我的对话框内容
    addChat(
        +uuid,
        {
          dateTime: new Date().toLocaleString(),
          text: message,
          inversion: true,        //为true代表我  false 代表机器人
          error: false,
          conversationOptions: null,
          requestOptions: { prompt: message, options: null },
        },
    )
    scrollToBottom()
    //isMobile.value = true    //关闭对话防止, 防止用户频繁输入
   // loading.value = true    //发送按钮颜色变为灰色,提示用户不可输入
    prompt.value = ''
    addChat(
        +uuid,
        {
          dateTime: new Date().toLocaleString(),
          text: "",
          loading: false,
          inversion: false,
          error: false,
          conversationOptions: null,
          requestOptions: { prompt: message, options: null },
        },
    )
  } else {
    alert("Please refresh the page");
    console.error('WebSocket 连接未就绪');
  }
// 获取历史信息，并将当前对话框信息传入到list当中
  msgHistoryAPI({})
}
//刷新重发
async function onRegenerate(index: number) {
  if (loading.value)
    return
  controller = new AbortController()

  const { requestOptions } = dataSources.value[index]
  const message = requestOptions?.prompt ?? ''
  let options: Chat.ConversationRequest = {}
  if (requestOptions.options)
    options = { ...requestOptions.options }
  loading.value = true
  updateChat(
      +uuid,
      index,
      {
        dateTime: new Date().toLocaleString(),
        text: 'Aha, Let me think again...',
        inversion: false,
        error: false,
        loading: true,
        conversationOptions: null,
        requestOptions: { prompt: message, ...options },
      },
  )
  try {
    await fetchChatAPIProcess<Chat.ConversationResponse>({
      prompt: message,
      keepIssue: "",
      options,
      signal: controller.signal,
      onDownloadProgress: ({ event }) => {
        const xhr = event.target
        const { responseText } = xhr
        // Always process the final line
        const lastIndex = responseText.lastIndexOf('\n')
        let chunk = responseText
        if (lastIndex !== -1)
          chunk = responseText.substring(lastIndex)
        try {
          const data = JSON.parse(chunk)
          updateChat(
              +uuid,
              index,
              {
                dateTime: new Date().toLocaleString(),
                text: data.text ?? '',
                inversion: false,
                error: false,
                loading: false,
                conversationOptions: { conversationId: data.conversationId, parentMessageId: data.id },
                requestOptions: { prompt: message, ...options },
              },
          )
        }
        catch (error) {
          //
        }
      },
    })
  }
  catch (error: any) {
    let errorMessage = error?.message ?? 'Something went wrong, please try again later.'
    if (error.message === 'canceled')
      errorMessage = 'Request canceled. Please try again.'
    updateChat(
        +uuid,
        index,
        {
          dateTime: new Date().toLocaleString(),
          text: errorMessage,
          inversion: false,
          error: true,
          loading: false,
          conversationOptions: null,
          requestOptions: { prompt: message, ...options },
        },
    )
  }
  finally {
    loading.value = false
  }
}
//删除
function handleDelete(index: number) {
  if (loading.value)
    return
  dialog.warning({
    title: 'Delete Message',
    content: 'Are you sure to delete this message?',
    positiveText: 'Yes',
    negativeText: 'No',
    onPositiveClick: () => {
      chatStore.deleteChatByUuid(+uuid, index)
      ms.success('Message deleted successfully.')
    },
  })
}
// 重发按钮
function handleRepeat(index:number){
  console.log(111,index)

}
function handleClear() {
  if (loading.value)
    return
  dialog.warning({
    title: 'Clear Chat',
    content: 'Are you sure to clear this chat?',
    positiveText: 'Yes',
    negativeText: 'No',
    onPositiveClick: () => {
      chatStore.clearChatByUuid(+uuid)
    },
  })
}
function handleEnter(event: KeyboardEvent) {
  if (!isMobile.value) {
    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault()
      handleSubmit()
      console.log(chatBoxRef.value)
    }
  }
}
function handleStop() {
  if (loading.value) {
    controller.abort()
    loading.value = false
  }
}
const placeholder = computed(() => {
  if (isMobile.value)
    return 'Ask me anything...'
  return 'Ask me anything... (Shift + Enter = line break)'
})
const buttonDisabled = computed(() => {
  return loading.value || !prompt.value || prompt.value.trim() === ''
})
const wrapClass = computed(() => {
  if (isMobile.value)
    return ['pt-14', 'pb-16']
  return []
})
const footerClass = computed(() => {
  let classes = ['p-4']
  if (isMobile.value)
    classes = ['p-2', 'pr-4', 'fixed', 'bottom-4', 'left-0', 'right-0', 'z-30', 'h-14', 'overflow-hidden']
  return classes
})

onMounted(() => {
  scrollToBottom()
  // console.log(getMessage.value.$refs.TextChatContainer)
})
const chatBoxRef = ref()
onUnmounted(() => {
  if (loading.value)
    controller.abort()

})

</script>

<template>
  <div class="flex flex-col h-full" :class="wrapClass">
    <main class="flex-1 overflow-hidden">
      <div>
        <router-link to="/login">登入</router-link>
        <router-link to="/changeUser">修改</router-link>
        <router-link to="/register">注册</router-link>
        <router-link to="/test">测试</router-link>
      </div>
      <div
          id="scrollRef"
          ref="scrollRef"
          class="h-full overflow-hidden overflow-y-auto"
          :class="[isMobile ? 'p-2' : 'p-4']"
      >
        <template v-if="!dataSources.length">
          <div class="flex items-center justify-center mt-4 text-center text-neutral-300">
            <SvgIcon icon="ri:bubble-chart-fill" class="mr-2 text-3xl" />
            <span>Aha~</span>
          </div>
        </template>

        <template v-else>
          <div>
            <Message
                ref="chatBoxRef"
                v-for="(item, index) of dataSources"
                :key="index"
                :date-time="item.dateTime"
                :text="item.text"
                :inversion="item.inversion"
                :error="item.error"
                :loading="item.loading"
                @regenerate="onRegenerate(index)"
                @delete="handleDelete(index)"
                @repeat="handleRepeat(index)"
            />
            <div class="flex justify-center">
              <NButton v-if="loading" ghost @click="handleStop">
                <template #icon>
                  <SvgIcon icon="ri:stop-circle-line" />
                </template>
                Stop Responding
              </NButton>
            </div>
          </div>
        </template>

      </div>
    </main>

    <footer :class="footerClass">
      <div class="flex items-center justify-between space-x-2">
        <HoverButton @click="handleClear">
          <span class="text-xl text-[#4f555e] dark:text-white">
            <SvgIcon icon="ri:delete-bin-line" />
          </span>
        </HoverButton>
        <NInput
            v-model:value="prompt"
            type="textarea"
            :autosize="{ minRows: 1, maxRows: 2 }"
            :placeholder="placeholder"
            @keypress="handleEnter"
        />
        <NButton type="primary" :disabled="buttonDisabled" @click="handleSubmit">
          <template #icon>
            <span class="dark:text-black">
              <SvgIcon icon="ri:send-plane-fill" />
            </span>
          </template>
        </NButton>
      </div>
    </footer>
  </div>
</template>